package com.yjck.jwt.Interceptor;


import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.yjck.jwt.config.JwtConstants;
import com.yjck.jwt.service.ISysUserService;
import com.yjck.jwt.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author EDZ
 */
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private ISysUserService sysUserService;

    @Value("${jwt.release}")
    private List<String> urls;


    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        // 从 http 请求头中取出 token
        String token = httpServletRequest.getHeader("Authorization");
        String requestURI = httpServletRequest.getRequestURI();
        String userId = "";

        for (String path : urls) {
            boolean b = filterUrls(path, requestURI);
            if (b) {
                return true;
            }
        }
        // 执行认证
        if (token == null) {
            throw new RuntimeException("无token，请重新登录");
        }

        String type = httpServletRequest.getHeader(JwtConstants.USER_TYPE_HEADER);
        boolean verify;
        // 效验token是否
        if (JwtConstants.APP.equals(type)) {
            verify = JwtUtil.verify(token, type);
            if (!verify) {
                throw new RuntimeException("401");
            }
        } else {
            verify = JwtUtil.verify(token, type);
            if (!verify) {
                throw new RuntimeException("401");
            }
            // 解析token
            try {
                userId = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException j) {
                throw new RuntimeException("401");
            }
            // 查询数据库
//            SysUser sysUser = sysUserService.findByUsername(userId);
//            if (StringUtils.isEmpty(sysUser)) {
//                throw new NullPointerException("401");
//            }
            // 查询权限列表

            // 对比权限列表


            // 请求头里面放入用户id
        }

        return true;
    }


    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }


    private boolean filterUrls(String excludePath, String reqUrl) {
        String regPath = getRegPath(excludePath);
        return Pattern.compile(regPath).matcher(reqUrl).matches();
    }

    private String getRegPath(String path) {
        char[] chars = path.toCharArray();
        int len = chars.length;
        StringBuilder sb = new StringBuilder();
        boolean preX = false;
        for (int i = 0; i < len; i++) {
            //遇到*字符
            if (chars[i] == '*') {
                //如果是第二次遇到*，则将**替换成.*
                if (preX) {
                    sb.append(".*");
                    preX = false;
                    //如果是遇到单星，且单星是最后一个字符，则直接将*转成[^/]*
                } else if (i + 1 == len) {
                    sb.append("[^/]*");
                    //否则单星后面还有字符，则不做任何动作，下一把再做动作
                } else {
                    preX = true;
                    continue;
                }
                //遇到非*字符
            } else {
                //如果上一把是*，则先把上一把的*对应的[^/]*添进来
                if (preX) {
                    sb.append("[^/]*");
                    preX = false;
                }
                //接着判断当前字符是不是?，是的话替换成.
                if (chars[i] == '?') {
                    sb.append('.');
                    //不是?的话，则就是普通字符，直接添进来
                } else {
                    sb.append(chars[i]);
                }
            }
        }
        return sb.toString();
    }

}
